package com.chenfan.finance.service.impl;

import com.chenfan.finance.dao.*;
import com.chenfan.finance.model.*;
import com.chenfan.finance.model.vo.AliPayExpendExportVO;
import com.chenfan.finance.model.vo.AliPayIncomeExportVO;
import com.chenfan.finance.model.vo.InvoiceSettlementExportVO;
import com.chenfan.finance.model.vo.TimeRange;
import com.chenfan.finance.service.TocAlipayOriginService;
import com.chenfan.finance.utils.DateTimeUtil;
import com.chenfan.finance.utils.FileUtil;
import com.chenfan.finance.utils.TrashBagList;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class TocAlipayOriginServiceImpl implements TocAlipayOriginService {

    private final Logger logger = LoggerFactory.getLogger(TocAlipayOriginServiceImpl.class);
    @Autowired
    private TocAlipayOriginMapper tocAlipayOriginMapper;
    @Autowired
    private TocAlipayMappingExpendMapper expendMapper;
    @Autowired
    private TocAlipayMappingIncomeMapper incomeMapper;
    @Autowired
    private CfSalesorderHeaderMapper cfSalesorderHeaderMapper;
    @Autowired
    private CfSalesorderDetailMapper cfSalesorderDetailMapper;
    @Autowired
    private CfRefundOrderHeaderMapper cfRefundOrderHeaderMapper;
    @Autowired
    private TocTradeRefundOrderHeaderMapper tocTradeRefundOrderHeaderMapper;
    @Autowired
    private TocTradeRefundOrderDetailMapper tocTradeRefundOrderDetailMapper;
    @Autowired
    private TocTradeOrderHeaderMapper tocTradeOrderHeaderMapper;
    @Autowired
    private TocTradeOrderDetailsMapper tocTradeOrderDetailsMapper;
    @Autowired
    private CfSalesdeliverDetailMapper cfSalesdeliverDetailMapper;
    @Autowired
    private CfSalesdeliverHeaderMapper cfSalesdeliverHeaderMapper;
    @Autowired
    private TocStockinOrderHeaderMapper tocStockinOrderHeaderMapper;
    @Autowired
    private TocImportDataService tocImportDataService;


    @Override
    public int compareData() {
        /**
         * 思路：
         * 1 先根据原始表的交易类型 判断 交易付款，在线支付（正向收入） 交易退款（逆向支出）
         * 2 如果是正向，则获取销售金额总和，和流水比对一波，如果匹配成功存入收入（条数和详情的一样）
         * 3 如果是逆向，则获取退款单
         * 业务类型 0交易付款 1在线支付 2交易退款 3交易分账 4其他 5收费 6提现 7转账（目前只处理0，1，2类型的）
         */
        TimeRange timeRange = new TimeRange();
        //因为测试11月份数据，现在12月，所以时间向前推1个月
        LocalDateTime now = LocalDateTime.now().minusMonths(1).minusDays(13);
        LocalDateTime min = LocalDateTime.of(now.toLocalDate(), LocalTime.MIN);
        LocalDateTime max = LocalDateTime.of(now.toLocalDate(), LocalTime.MAX);

        timeRange.setStart(min);
        timeRange.setEnd(max);
        List<TocAlipayOrigin> allDataByMonth = tocAlipayOriginMapper.getAllDataByMonth(timeRange);


        timeRange.setStart(LocalDateTime.of(LocalDate.now(), LocalTime.MIN).with(TemporalAdjusters.firstDayOfMonth()).minusMonths(2));
        timeRange.setEnd(LocalDateTime.of(LocalDate.now(), LocalTime.MAX).with(TemporalAdjusters.lastDayOfMonth()).minusMonths(2));
        //获取原始表所有数据(每月的)
        logger.info("原始表共" + allDataByMonth.size() + "条数据,开始匹配------------------------------------");
        a:for(TocAlipayOrigin x :allDataByMonth){
            Integer tradePay = 0;
            Integer payOnline = 1;
            Integer refundPay = 2;
            //判断交易类型
            if(x.getBusinessType().equals(tradePay) || x.getBusinessType().equals(payOnline)){
                //正向单据获取tid,因为单据以T2000开头，之后才是tid，所以要截取
                String tid = getTidFromOrderNo(x.getTid());
                x.setTid(tid);
                //1 比对出库单详情总支付金额
                List<ReferenceTable> referenceIdByTid = tocImportDataService.getReferenceIdByTid(1,timeRange.getStart(), timeRange.getEnd(), tid);
                if(!CollectionUtils.isEmpty(referenceIdByTid)){
                    List<TocSalesDeliverHeader> deliverHeader = cfSalesdeliverHeaderMapper.getListByIds(referenceIdByTid.stream().map(ReferenceTable::getId).collect(Collectors.toList()),timeRange);
                    if(!CollectionUtils.isEmpty(deliverHeader)){
                        for(TocSalesDeliverHeader h:deliverHeader){
                            //因为主表的数据没有总支付金额，所以去详情比对
                            List<TocSalesDeliverDetail> detailsList = cfSalesdeliverDetailMapper.getDetailsListByStockOutId(h.getStockoutId(), timeRange);
                            if(!CollectionUtils.isEmpty(detailsList)){
                                BigDecimal totalAmount = detailsList.stream().map(TocSalesDeliverDetail::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                                if(totalAmount.compareTo(x.getIncomeAmount()) == 0){
                                    try {
                                        createAlipayIncomeStockOut(x,h,detailsList,timeRange);
                                        //调到外层循环去
                                        continue a;
                                    } catch (Exception e) {
                                        logger.error(e.getMessage());
                                    }
                                }else{
                                    //使用垃圾袋算法尝试匹配，不行就算了，匹配原始订单去了
                                    List<TocSalesDeliverDetail> details = new TrashBagList<TocSalesDeliverDetail>().trashBag(detailsList, TocSalesDeliverDetail::getRecId, TocSalesDeliverDetail::getTotalAmount, x.getIncomeAmount());
                                    if(!CollectionUtils.isEmpty(details)){
                                        try {
                                            createAlipayIncomeStockOut(x,h,details,timeRange);
                                            //调到外层循环去
                                            continue a;
                                        } catch (Exception e) {
                                            logger.error(e.getMessage());
                                        }
                                    }
                                }
                            }
                        }
                    }
                }


                //2 比对原始订单 先比对主表金额，不成功再比对详情金额
                List<TocTradeOrderHeader> listByTid = tocTradeOrderHeaderMapper.getListByTid(tid, timeRange);
                if(!CollectionUtils.isEmpty(listByTid)){
                    for(TocTradeOrderHeader z:listByTid) {
                        if (z.getReceivable().compareTo(x.getIncomeAmount()) == 0) {
                            //如果能匹配上，获取原始订单详情，生成收入mapping
                            List<TocTradeOrderDetails> detailList = tocTradeOrderDetailsMapper.getDetailListByTid(tid, timeRange);
                            //过滤掉有退款的单子
                            List<TocTradeOrderDetails> filteredList = detailList.stream().filter(a -> a.getRefundStatus() != 5).collect(Collectors.toList());
                            BigDecimal totalPaid = filteredList.stream().map(TocTradeOrderDetails::getPaid).reduce(BigDecimal.ZERO, BigDecimal::add);
                            if(totalPaid.compareTo(BigDecimal.ZERO) == 1 && totalPaid.compareTo(x.getIncomeAmount()) == 0){
                                try {
                                    createAlipayIncomeOrigin(x,z,filteredList,timeRange);
                                    //调到外层循环去
                                    continue a;
                                } catch (Exception e) {
                                    logger.error(e.getMessage());
                                }
                            }
                        }else{
                            //匹配一下原始订单详情(和主表用tid关联的)
                            List<TocTradeOrderDetails> detailList = tocTradeOrderDetailsMapper.getDetailListByTid(tid, timeRange);
                            //过滤掉退款单子
                            List<TocTradeOrderDetails> filteredList = detailList.stream().filter(a -> a.getRefundStatus() != 5).collect(Collectors.toList());
                            //总支付金额
                            BigDecimal totalPaid = filteredList.stream().map(TocTradeOrderDetails::getPaid).reduce(BigDecimal.ZERO, BigDecimal::add);
                            if(!CollectionUtils.isEmpty(filteredList)){
                                if(totalPaid.compareTo(x.getIncomeAmount()) == 0){
                                    try {
                                        createAlipayIncomeOrigin (x,z,filteredList,timeRange);
                                        //调到外层循环去
                                        continue a;
                                    } catch (Exception e) {
                                        logger.error(e.getMessage());
                                    }
                                }
                            }else{
                                //使用垃圾袋算法尝试匹配，不行就算了，匹配销售订单去了
                                List<TocTradeOrderDetails> details = new TrashBagList<TocTradeOrderDetails>().trashBag(filteredList, TocTradeOrderDetails::getRecId, TocTradeOrderDetails::getPaid, x.getIncomeAmount());
                                if(!CollectionUtils.isEmpty(details)){
                                    try {
                                        createAlipayIncomeOrigin(x,z,details,timeRange);
                                        //调到外层循环去
                                        continue a;
                                    } catch (Exception e) {
                                        logger.error(e.getMessage());
                                    }
                                }
                            }
                        }
                    }
                }

                //3 获取销售订单详情
                List<TocSalesOrderDetail> detailListByTradeId = cfSalesorderDetailMapper.getDetailListByTid(tid,timeRange);
                //总应支付
                BigDecimal totalShareAmount = detailListByTradeId.stream().map(TocSalesOrderDetail::getShareAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                //总邮费
                BigDecimal totalSharePost = detailListByTradeId.stream().map(TocSalesOrderDetail::getSharePost).reduce(BigDecimal.ZERO, BigDecimal::add);
                //总支付
                BigDecimal totalAmount = totalShareAmount.add(totalSharePost);

                //先匹配一波，有可能成功
                if(totalAmount.compareTo(x.getIncomeAmount()) == 0){
                    try {
                        //全正向的
                        createAlipayIncome(x,detailListByTradeId,timeRange);
                        //调到外层循环去
                        continue a;
                    } catch (Exception e) {
                        logger.error(e.getMessage());
                    }
                }else{
                    //这里也要加入垃圾袋算法
                    //使用垃圾袋算法尝试匹配，不行就算了
                    List<TocSalesOrderDetail> details = new TrashBagList<TocSalesOrderDetail>().trashBag(detailListByTradeId, TocSalesOrderDetail::getRecId, TocSalesOrderDetail::getShareAmount, x.getIncomeAmount());
                    if(!CollectionUtils.isEmpty(details)){
                        try {
                            createAlipayIncome(x,detailListByTradeId,timeRange);
                            //调到外层循环去
                            continue a;
                        } catch (Exception e) {
                            logger.error(e.getMessage());
                        }
                    }

                    //部分退款和全退款都在这里处理
                    List<TocTradeRefundOrderHeader> refundList = tocTradeRefundOrderHeaderMapper.getListByTid(tid,timeRange);
                    //总退款金额
                    BigDecimal totalRefund = refundList.stream().map(TocTradeRefundOrderHeader::getActualRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                    //如果总支付金额减去总退款等于 支付宝流水中金额，则记为支出
                    if(totalAmount.compareTo(BigDecimal.ZERO) == 1
                            && totalRefund.compareTo(BigDecimal.ZERO) == 1
                            && totalAmount.subtract(totalRefund).compareTo(x.getIncomeAmount()) == 0){
                        //这种是全退款无邮费的情况,查一下对应的退款单详情
                        List<TocTradeRefundOrderDetail> refundDetailList = tocTradeRefundOrderDetailMapper.getDetailListByRefundCode(refundList.get(0).getRefundNo(), timeRange);
                        //给退款详情刷一下skuCode
                        refundDetailList.forEach(r->{
                            //给退款详情刷一下skuCode
                            String skuCode = tocTradeOrderDetailsMapper.getSkuCodeBySpecId(r.getSpecId(), timeRange);
                            if(!StringUtils.isEmpty(skuCode)){
                                r.setSpecNo(skuCode);
                                //没匹配到再去销售订单详情中查询一下
                            }else{
                                String skuCode2 = cfSalesorderDetailMapper.getSkuCodeBySpecId(r.getSpecId(), timeRange);
                                if(!StringUtils.isEmpty(skuCode2)){
                                    r.setSpecNo(skuCode);
                                }
                            }
                        });

                        //将销售订单详情和退款单详情匹配，把退款那部分sku的单子剔除
                        List<String> salesSkuList = detailListByTradeId.stream().map(a -> a.getSpecNo()).distinct().collect(Collectors.toList());
                        List<String> refundSkuList = refundDetailList.stream().map(b -> b.getSpecNo()).distinct().collect(Collectors.toList());
                        //求差集,即为要存入mapping表的
                        List<String> filteredCollect = salesSkuList.stream().filter(a -> refundSkuList.stream().noneMatch(a::equals)).collect(Collectors.toList());
                        List<TocSalesOrderDetail> newList = new ArrayList<>();
                        for(TocSalesOrderDetail d: detailListByTradeId){
                            for(String c: filteredCollect){
                                if(d.getSpecNo().equals(c)){
                                    newList.add(d);
                                }
                            }
                        }
                        try {
                            createAlipayIncome(x,newList,timeRange);
                            //调到外层循环去
                            continue a;
                        } catch (Exception e) {
                            logger.error(e.getMessage());
                        }
                    }else if(totalRefund.compareTo(BigDecimal.ZERO) == 1
                            && totalSharePost.compareTo(BigDecimal.ZERO) == 1
                            && totalShareAmount.compareTo(totalRefund) == 0){
                        //这种是退款后剩下邮费的情况,那么就只要有邮费这一笔
                        List<TocSalesOrderDetail> filteredList = detailListByTradeId.stream().filter(a -> a.getSharePost().equals(totalSharePost)).collect(Collectors.toList());
                        try {
                            createAlipayIncomeWithPost(x,filteredList,timeRange);
                            //调到外层循环去
                            continue a;
                        } catch (Exception e) {
                            logger.error(e.getMessage());
                        }
                    }
                }


            }else if(x.getBusinessType().equals(refundPay)){
                //逆向可以匹配原始退款单，根据商户订单号截取(有部分数据没有给退款单号)
                String refundNo = getRefundNo(x.getTid());
                //从备注里截取tid
                String tid = getTidFromRemarkRefund(x.getRemark());
                x.setTid(tid);
                //去退款单查询，匹配金额，如果匹配上存入mapping支出表
                List<TocTradeRefundOrderHeader> listByRefundCode = tocTradeRefundOrderHeaderMapper.getListByRefundCode(refundNo,timeRange);
                if(!CollectionUtils.isEmpty(listByRefundCode)){
                    //退款单主表已经有退款金额了
                    TocTradeRefundOrderHeader t = listByRefundCode.get(0);
                    if(t.getActualRefundAmount().add(x.getExpendAmount()).compareTo(BigDecimal.ZERO) == 0){
                        //获取主表对应的详情
                        List<TocTradeRefundOrderDetail> detailList= tocTradeRefundOrderDetailMapper.getDetailListByRefundCode(refundNo,timeRange);
                        if(!CollectionUtils.isEmpty(detailList)){
                            try {
                                createAlipayExpend(x,t,detailList,timeRange);
                                //调到外层循环去
                                continue a;
                            } catch (Exception e) {
                                logger.error(e.getMessage());
                            }
                        }
                    }else{
                        //如果和退款单主表金额不匹配，再去匹配一次退款单详情
                        //获取主表对应的详情
                        List<TocTradeRefundOrderDetail> detailList= tocTradeRefundOrderDetailMapper.getDetailListByRefundCode(refundNo,timeRange);
                        //总退款
                        BigDecimal totalAmount = detailList.stream().map(TocTradeRefundOrderDetail::getTotalAmount).reduce(BigDecimal.ZERO,BigDecimal::add);
                        if(totalAmount.add(x.getExpendAmount()).compareTo(BigDecimal.ZERO) == 0){
                            try {
                                createAlipayExpend(x,t,detailList,timeRange);
                                //调到外层循环去
                                continue a;
                            } catch (Exception e) {
                                logger.error(e.getMessage());
                            }
                        }
                    }

                    //匹配一下历史订单
                }
            }
        }
        logger.info("全部匹配完成---------------------------------------------");
        return 0;
    }

    private static BigDecimal addAll(BigDecimal ... alipayAmount) {
        BigDecimal all=BigDecimal.ZERO;
        for (BigDecimal bigDecimal : alipayAmount) {
            if(bigDecimal==null){
                bigDecimal= BigDecimal.ZERO;
            }
            all = all.add(bigDecimal);
        }
        return all;
    }

    /**
     * 从字符换里面截取单号
     * @param refundNoString
     * @return
     */
    private static String getRefundNo(String refundNoString){
        //退款单号是17位的
        int length = refundNoString.length() - 17 > 0 ? refundNoString.length() - 17 : refundNoString.length();
        refundNoString = refundNoString.substring(length);
        return refundNoString;
    }

    /**
     * 从备注里面截取tid
     * @param refundNoString
     * @return
     */
    private static String getTidFromRemark(String refundNoString){
        StringBuilder s = new StringBuilder(refundNoString);
        int i = s.lastIndexOf("-");
        String substring = s.substring(i + 6);
        return substring;

    }

    /**
     * 从备注里面截取tid(退款单)
     * @param remark
     * @return
     */
    private static String getTidFromRemarkRefund(String remark){
        StringBuilder s = new StringBuilder(remark);
        int i = s.lastIndexOf("P");
        String substring = s.substring(i + 1);
        return substring;

    }

    /**
     * 从商户订单号里面截取tid
     * @param OrderNo
     * @return
     */
    private static String getTidFromOrderNo(String OrderNo){
        StringBuilder s = new StringBuilder(OrderNo);
        int i = s.lastIndexOf("P");
        String substring = s.substring(i + 1);
        return substring;

    }
    /**
     * 以详情维度插入收入mapping表
     * @param tocAlipayOrigin
     * @param details
     */
    public void createAlipayIncome(TocAlipayOrigin tocAlipayOrigin,List<TocSalesOrderDetail> details,TimeRange timeRange){
        for(TocSalesOrderDetail detail:details){
            TocAlipayMappingIncome t = new TocAlipayMappingIncome();
            t.setFinanceNo(tocAlipayOrigin.getFinanceNo());
            t.setTaobaoSoNo(detail.getSrcTid());
            t.setTaobaoSoItemNo(detail.getSrcOid());
            //有些详情找不到对应的主表,可能是数据问题
            List<TocSalesOrderHeader> byTradeId = cfSalesorderHeaderMapper.getByTradeId(detail.getTradeId(),timeRange);
            if(!CollectionUtils.isEmpty(byTradeId)){
                t.setPayDate(byTradeId.get(0).getPayTime());
                t.setShopId(byTradeId.get(0).getShopId().intValue());
                //订单号
                t.setOrderCode(byTradeId.get(0).getTradeNo());
                //出库单号
                t.setOutBoundCode(byTradeId.get(0).getStockoutNo());
            }
            t.setReceivedDate(tocAlipayOrigin.getAccountDate());
            t.setSpuCode(detail.getGoodsNo());
            t.setSkuCode(detail.getSpecNo());
            t.setSaleQty(detail.getNum().intValue());
            t.setConsignQty(detail.getNum().intValue());
            t.setTotalAmtAfterShare(addAll(detail.getSharePost(),detail.getShareAmount()));
            t.setDetailReceived(tocAlipayOrigin.getIncomeAmount());
            t.setAccountNos(tocAlipayOrigin.getFinanceNo());
            t.setReceivedMonth(tocAlipayOrigin.getAccountDate().toString());
            t.setGoodsName(detail.getGoodsName());
            t.setTaxRate(detail.getTaxRate());
            //店铺简称去远程获取吧？
            //t.setShopNickname(tocAlipayOrigin.getShopNickName());
            t.setReceivedAmt(tocAlipayOrigin.getIncomeAmount());
            t.setCheckFlag(1);
            incomeMapper.insert(t);
            //生成成功后要把原始单的状态改为对账成功
            tocAlipayOriginMapper.updateCheckFlagByFinanceNo(tocAlipayOrigin.getFinanceNo(),timeRange);
        }

    }
    /**
     * 以详情维度插入支出mapping表
     * @param tocAlipayOrigin
     * @param
     */
    public void createAlipayExpend(TocAlipayOrigin tocAlipayOrigin,TocTradeRefundOrderHeader tocTradeRefundOrderHeader,List<TocTradeRefundOrderDetail> details,TimeRange timeRange){
        for(TocTradeRefundOrderDetail detail:details){
            TocAlipayMappingExpend t = new TocAlipayMappingExpend();
            t.setFinanceNo(tocAlipayOrigin.getFinanceNo());
            t.setTaobaoSoNo(tocTradeRefundOrderHeader.getTid());
            t.setTaobaoSoItemNo(detail.getOid());
            t.setTaobaoRefundNo(detail.getRefundNo());
            t.setAccountNos(tocAlipayOrigin.getFinanceNo());
            //关系表
            List<ReferenceTable> referenceIdByTid = tocImportDataService.getReferenceIdByTid(3, timeRange.getStart(), timeRange.getEnd(), tocAlipayOrigin.getTid());
            List<TocStockinOrderHeader> list = tocStockinOrderHeaderMapper.getListByIds(referenceIdByTid.stream().map(ReferenceTable::getId).collect(Collectors.toList()), timeRange);
            if(!CollectionUtils.isEmpty(list)){
                t.setRecordCode(list.get(0).getStockinNo());
            }
            t.setPayDate(DateTimeUtil.dateToLocalDateTime(tocTradeRefundOrderHeader.getCreated()));
            t.setReceivedDate(tocAlipayOrigin.getAccountDate());
            t.setSpuCode(detail.getGoodsNo());
            //先去原始订单详情中获取skucode
            String skuCode = tocTradeOrderDetailsMapper.getSkuCodeBySpecId(detail.getSpecId(), timeRange);
            if(!StringUtils.isEmpty(skuCode)){
                t.setSkuCode(skuCode);
                //没匹配到再去销售员订单详情中查询一下
            }else{
                String skuCode2 = cfSalesorderDetailMapper.getSkuCodeBySpecId(detail.getSpecId(), timeRange);
                if(!StringUtils.isEmpty(skuCode2)){
                    t.setSkuCode(skuCode2);
                }
            }
            t.setRefundQty(detail.getNum().intValue());
            t.setActualRefundAmt(tocTradeRefundOrderHeader.getRefundAmount());
            t.setExpenseAmt(tocTradeRefundOrderHeader.getActualRefundAmount());
            t.setReceivedMonth(tocAlipayOrigin.getAccountDate().toString());
            t.setGoodsName(detail.getGoodsName());
            //店铺简称去远程获取吧？
            t.setShopId(tocTradeRefundOrderHeader.getShopId().intValue());
            //t.setShopNickname(tocAlipayOrigin.getShopNickName());
            //税率来个默认值 0
            t.setPriceWithoutTax(BigDecimal.ZERO);
            t.setCheckFlag(1);
            expendMapper.insert(t);
        }
        //生成成功后要把原始单的状态改为对账成功
        tocAlipayOriginMapper.updateCheckFlagByFinanceNo(tocAlipayOrigin.getFinanceNo(),timeRange);
    }


    /**
     * 以详情维度插入收入mapping表(来自原始订单)
     * @param tocAlipayOrigin
     * @param details
     */
    public void createAlipayIncomeOrigin(TocAlipayOrigin tocAlipayOrigin,TocTradeOrderHeader header,List<TocTradeOrderDetails> details,TimeRange timeRange){
        for(TocTradeOrderDetails detail:details){
            TocAlipayMappingIncome t = new TocAlipayMappingIncome();
            t.setFinanceNo(tocAlipayOrigin.getFinanceNo());
            t.setTaobaoSoNo(detail.getTid());
            t.setTaobaoSoItemNo(detail.getOid());
            //根据原始订单中的tradeid找出库单
            t.setPayDate(DateTimeUtil.dateToLocalDateTime(header.getCreated()));
            t.setShopId(header.getShopId().intValue());
            t.setReceivedDate(tocAlipayOrigin.getAccountDate());
            t.setSpuCode(detail.getGoodsNo());
            t.setSkuCode(detail.getSpecNo());
            t.setSaleQty(detail.getNum().intValue());
            t.setConsignQty(detail.getNum().intValue());
            t.setTotalAmtAfterShare(addAll(detail.getSharePost(),detail.getShareAmount()));
            t.setDetailReceived(tocAlipayOrigin.getIncomeAmount());
            t.setAccountNos(tocAlipayOrigin.getFinanceNo());
            t.setReceivedMonth(tocAlipayOrigin.getAccountDate().toString());
            t.setGoodsName(detail.getGoodsName());
            //税率来个默认值 0
            t.setTaxRate(BigDecimal.ZERO);
            //店铺简称去远程获取吧？
            //t.setShopNickname(tocAlipayOrigin.getShopNickName());
            t.setReceivedAmt(tocAlipayOrigin.getIncomeAmount());
            t.setCheckFlag(1);
            t.setOutBoundCode(header.getStockoutNo());
            List<ReferenceTable> referenceIdByTid = tocImportDataService.getReferenceIdByTid(2, timeRange.getStart(), timeRange.getEnd(), tocAlipayOrigin.getTid());
            List<TocSalesOrderHeader> list = cfSalesorderHeaderMapper.getListByIds(referenceIdByTid.stream().map(ReferenceTable::getId).collect(Collectors.toList()), timeRange);
            if(!CollectionUtils.isEmpty(list)){
               t.setOrderCode(list.get(0).getTradeNo());
               if(StringUtils.isEmpty(t.getOutBoundCode())){
                   t.setOutBoundCode(list.get(0).getStockoutNo());
               }
            }
            incomeMapper.insert(t);
            //生成成功后要把原始单的状态改为对账成功
            tocAlipayOriginMapper.updateCheckFlagByFinanceNo(tocAlipayOrigin.getFinanceNo(),timeRange);
        }

    }

    /**
     * 以详情维度插入收入mapping表(来自出库单)
     * @param tocAlipayOrigin
     * @param header
     * @param detailsList
     * @param timeRange
     */
    public void createAlipayIncomeStockOut(TocAlipayOrigin tocAlipayOrigin,TocSalesDeliverHeader header,List<TocSalesDeliverDetail> detailsList,TimeRange timeRange){
        for(TocSalesDeliverDetail detail:detailsList){
            TocAlipayMappingIncome t = new TocAlipayMappingIncome();
            t.setShopId(header.getShopId());
            t.setFinanceNo(tocAlipayOrigin.getFinanceNo());
            t.setTaobaoSoNo(tocAlipayOrigin.getTid());
            t.setTaobaoSoItemNo(detail.getSrcOid());
            t.setPayDate(DateTimeUtil.dateToLocalDateTime(header.getCreated()));
            t.setReceivedDate(tocAlipayOrigin.getAccountDate());
            t.setSpuCode(detail.getGoodsNo());
            t.setSkuCode(detail.getSpecNo());
            t.setSaleQty(detail.getNum().intValue());
            t.setConsignQty(detail.getNum().intValue());
            t.setTotalAmtAfterShare(detail.getTotalAmount());
            t.setDetailReceived(tocAlipayOrigin.getIncomeAmount());
            t.setAccountNos(tocAlipayOrigin.getFinanceNo());
            t.setReceivedMonth(tocAlipayOrigin.getAccountDate().toString());
            t.setGoodsName(detail.getGoodsName());
            //税率来个默认值 0
            t.setTaxRate(BigDecimal.ZERO);
            //店铺简称去远程获取吧？
            //t.setShopNickname(tocAlipayOrigin.getShopNickName());
            t.setReceivedAmt(tocAlipayOrigin.getIncomeAmount());
            t.setCheckFlag(1);
            t.setOutBoundCode(header.getStockoutNo());
            t.setOrderCode(header.getSrcOrderNo());
            incomeMapper.insert(t);
            //生成成功后要把原始单的状态改为对账成功
            tocAlipayOriginMapper.updateCheckFlagByFinanceNo(tocAlipayOrigin.getFinanceNo(),timeRange);
        }
    }

    /**
     * 以详情维度插入收入mapping表(来自单独邮费)
     * @param tocAlipayOrigin
     * @param details
     */
    public void createAlipayIncomeWithPost(TocAlipayOrigin tocAlipayOrigin,List<TocSalesOrderDetail> details,TimeRange timeRange){
        for(TocSalesOrderDetail detail:details){
            if(detail.getSharePost() == null || detail.getSharePost().compareTo(BigDecimal.ZERO) == 0){
                continue;
            }
            TocAlipayMappingIncome t = new TocAlipayMappingIncome();
            t.setFinanceNo(tocAlipayOrigin.getFinanceNo());
            t.setTaobaoSoNo(detail.getSrcTid());
            t.setTaobaoSoItemNo(detail.getSrcOid());
            //有些详情找不到对应的主表,可能是数据问题
            List<TocSalesOrderHeader> byTradeId = cfSalesorderHeaderMapper.getByTradeId(detail.getTradeId(),timeRange);
            if(!CollectionUtils.isEmpty(byTradeId)){
                t.setPayDate(byTradeId.get(0).getPayTime());
                t.setShopId(byTradeId.get(0).getShopId().intValue());
                //订单号
                t.setOrderCode(byTradeId.get(0).getTradeNo());
                //出库单号
                t.setOutBoundCode(byTradeId.get(0).getStockoutNo());
            }
            t.setReceivedDate(tocAlipayOrigin.getAccountDate());
            t.setSpuCode("YF001");
            t.setSkuCode(detail.getSpecNo());
            t.setSaleQty(detail.getNum().intValue());
            t.setConsignQty(detail.getNum().intValue());
            t.setTotalAmtAfterShare(addAll(detail.getSharePost(),detail.getShareAmount()));
            t.setDetailReceived(tocAlipayOrigin.getIncomeAmount());
            t.setAccountNos(tocAlipayOrigin.getFinanceNo());
            t.setReceivedMonth(tocAlipayOrigin.getAccountDate().toString());
            t.setGoodsName(detail.getGoodsName());
            t.setTaxRate(detail.getTaxRate());
            //店铺简称去远程获取吧？
            //t.setShopNickname(tocAlipayOrigin.getShopNickName());
            t.setReceivedAmt(tocAlipayOrigin.getIncomeAmount());
            t.setCheckFlag(1);
            incomeMapper.insert(t);
            //生成成功后要把原始单的状态改为对账成功
            tocAlipayOriginMapper.updateCheckFlagByFinanceNo(tocAlipayOrigin.getFinanceNo(),timeRange);
        }

    }

    @Override
    public int exportExpend(HttpServletResponse response){
        TimeRange timeRange = new TimeRange();
        //因为测试11月份数据，现在12月，所以时间向前推1个月
        timeRange.setStart(LocalDateTime.of(LocalDate.now(), LocalTime.MIN).with(TemporalAdjusters.firstDayOfMonth()).minusMonths(1));
        timeRange.setEnd(LocalDateTime.of(LocalDate.now(), LocalTime.MAX).with(TemporalAdjusters.lastDayOfMonth()).minusMonths(1));
        List<AliPayExpendExportVO> dataForExport = expendMapper.getDataForExport(timeRange);
        try {
            FileUtil.exportExcelV2(
                    dataForExport,
                    "mapping支出",
                    "导出人：" + 1,
                    "mapping支出",
                    AliPayExpendExportVO.class,
                    "mapping支出.xlsx",
                    response);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return 1;
    }

    @Override
    public int exportIncome(HttpServletResponse response) {
        TimeRange timeRange = new TimeRange();
        //因为测试11月份数据，现在12月，所以时间向前推1个月
        timeRange.setStart(LocalDateTime.of(LocalDate.now(), LocalTime.MIN).with(TemporalAdjusters.firstDayOfMonth()).minusMonths(1));
        timeRange.setEnd(LocalDateTime.of(LocalDate.now(), LocalTime.MAX).with(TemporalAdjusters.lastDayOfMonth()).minusMonths(1));
        List<TocAlipayMappingIncome> dataForExport = incomeMapper.getDataForExport(timeRange);
        try {
            FileUtil.exportExcelV2(
                    dataForExport,
                    "mapping收入",
                    "导出人：" + 1,
                    "mapping收入",
                    AliPayIncomeExportVO.class,
                    "mapping收入.xlsx",
                    response);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return 1;
    }
}
